﻿using System;
using System.Net;
using System.Windows;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Practices.Composite.Events;
using Core.Infrastructure.AnimationService;
using Microsoft.Practices.Unity;
using Core.Infrastructure.Settings;
using Core.Infrastructure.ViewModelBase;
using Microsoft.Practices.Composite.Presentation.Commands;
using System.Collections.Generic;
using Core.Model;
using ThemeLoader;
using Core.Infrastructure.ErrorReportService;

namespace Core.ScreenStore.ViewModel
{
    public class ThemeSelectViewModel : ViewModelBase
    {
        private IThemeLoader themeLoader;
        private IThemeManager themeManager;
        private IEnumerable<ThemeModel> themes;
        private IErrorReportService errorReportService;
        private bool isBusy;

        public override bool IsActive { get; set; }

        public IEnumerable<ThemeModel> Themes 
        {
            get
            {
                return themes;
            }
            private set
            {
                themes = value;
                base.RaisePropertyChanged(() => this.Themes);
            }
        }

        public bool IsBusy
        {
            get
            {
                return isBusy;
            }
            set
            {
                isBusy = value;
                base.RaisePropertyChanged(() => this.IsBusy);
            }
        }

        public DelegateCommand<ThemeModel> SelectThemeCommand { get; private set; }

        public ThemeSelectViewModel(IEventAggregator eventAggregator,
                                    IAnimationService animationService,
                                    IUnityContainer container,
                                    ISettings settings,
                                    IThemeLoader themeLoader,
                                    IThemeManager themeManager,
                                    IEnumerable<ThemeModel> themesInfo,
                                    IErrorReportService errorReportService)
            : base(eventAggregator, animationService, container, settings)
        {
            AnimationService = animationService;
            Settings = settings;
            this.themeLoader = themeLoader;
            this.themeManager = themeManager;
            this.errorReportService = errorReportService;

            Loaded = new DelegateCommand<object>(OnLoad);
            Unloaded = new DelegateCommand<object>(OnUnload);

            this.Themes = themesInfo;

            SelectThemeCommand = new DelegateCommand<ThemeModel>(theme => SelectTheme(theme),
                                                                  theme => CanSelectTheme(theme));
        }

        public void SelectTheme(ThemeModel theme)
        {
            if (!CanSelectTheme(theme))
            {
                throw new InvalidOperationException("Call CanSelectTheme first, to determine if it can be called");
            }

            if (theme.IsLoaded)
            {
                themeManager.ApplyTheme(theme.Styles);
            }
            else
            {
                IsBusy = true;

                this.themeLoader.DownloadTheme(themeZipFilePath: theme.ZippedThemeFilePath, 
                                               themeContentFileName: theme.ResourcePath, 
                                               loadFinishedHandler: e => ThemeDownloadComplete(theme, e));

            }        
        }

        public bool CanSelectTheme(ThemeModel theme)
        {
            return !IsBusy;
        }

        private void ThemeDownloadComplete(ThemeModel theme, ThemeDownloadedEventArgs e)
        {
            IsBusy = false;

            if (e.Error == null)
            {
                theme.IsLoaded = true;
                theme.Styles = e.Result;
                themeManager.ApplyTheme(e.Result);
            }
            else
            {
                HandleThemeLoadError(theme);
            }  
        }

        private void HandleThemeLoadError(ThemeModel themeToRemove)
        {
            this.Themes = this.Themes.Where(theme => theme != themeToRemove).ToList();

            errorReportService.Report("Cannot load style, style will be removed from list");
        }

        #region ViewModelBase abstract implementation

        public override void OnUnload(object obj)
        {
            this.IsActive = false;
        }

        public override void OnLoad(object obj)
        {
            this.IsActive = true;
        }

        #endregion
    }
}
